package org.luxor.commons.zookeeper.component;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.apache.curator.framework.recipes.cache.NodeCacheListener;
import org.luxor.commons.zookeeper.config.properties.ZookeeperProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Hashtable;
import java.util.List;
import java.util.Optional;

/**
 * 节点监听器，可监听节点对的应增、删、改操作
 *
 * @author Mr.Yan  @date: 2020/12/23
 */
public class NodeCacheWatcher {
    private static final Logger logger = LoggerFactory.getLogger(NodeCacheWatcher.class);

    private Hashtable<String, NodeCache> nodeCaches = new Hashtable<String, NodeCache>();
    private CuratorFramework curatorFramework;
    private ZookeeperProperties zookeeperProperties;

    public NodeCacheWatcher(CuratorFramework curatorFramework, ZookeeperProperties zookeeperProperties) {
        this.zookeeperProperties = zookeeperProperties;
        this.curatorFramework = curatorFramework;
    }

    /**
     * 添加
     *
     * @param nodeCacheListener 监听接收器
     */
    public void addWatcher(String path, NodeCacheListener nodeCacheListener) throws Exception {
        if (!StringUtils.hasText(path)) {
            return;
        }
        List<String> ignores = zookeeperProperties.getListenerIgnores();
        if (!CollectionUtils.isEmpty(ignores) && CollectionUtils.contains(ignores.iterator(), path)) {
            logger.warn("NodeWatcher监听器:[ {} ] 注册，因白名单配置原因被忽略", nodeCacheListener.getClass());
            return;
        }
        if (this.nodeCaches.containsKey(path)) {
            logger.warn("NodeWatcher监听器:[ {} ] 注册，因存在其它观察对象被忽略", nodeCacheListener.getClass());
            return;
        }

        NodeCache nodeCache = new NodeCache(curatorFramework, path);
        nodeCache.getListenable().addListener(nodeCacheListener);
        // 添加监听器记录
        this.nodeCaches.put(path, nodeCache);
        // 开启监听
        nodeCache.start(true);
    }

    /**
     * 获取
     */
    public Optional<NodeCache> getWatcher(String path) {
        if (StringUtils.hasText(path)) {
            return Optional.ofNullable(this.nodeCaches.get(path));

        }
        return Optional.empty();
    }

    /**
     * 移除
     */
    public void removeWatcher(String path) {
        try {
            if (StringUtils.hasText(path)) {
                this.nodeCaches.get(path).close();
            }
        } catch (Exception e) {
            // .ignore
        }

    }

}
